// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Microsoft.ML.Probabilistic.Serialization
{
    using System;
    using System.Runtime.Serialization;
    using System.Xml;

    /// <summary>
    /// A data contract resolver that dynamically resolves known types.
    /// </summary>
    public class InferDataContractResolver : DataContractResolver
    {
        // URN prefix of namespaces generated by our contract resolver
        private const string nsPrefix = "urn:x-research.microsoft.com:Infer.NET:assemblyname:";

        public override bool TryResolveType(
            Type type,
            Type declaredType,
            DataContractResolver knownTypeResolver,
            out XmlDictionaryString typeName,
            out XmlDictionaryString typeNamespace)
        {
            if (knownTypeResolver.TryResolveType(type, declaredType, knownTypeResolver, out typeName, out typeNamespace))
            {
                return true;
            }

            var dict = new XmlDictionary(2);
            typeName = dict.Add(type.FullName); 
            typeNamespace = dict.Add(String.Concat(nsPrefix, type.Assembly.FullName));
            return true;
        }

        public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
        {
            var ty = knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, knownTypeResolver);

            if (ty != null) return ty;

            if (typeNamespace.StartsWith(nsPrefix)) // Is this our namespace?
                return Type.GetType($"{typeName}, {typeNamespace.Substring(nsPrefix.Length)}"); // If yes, try to load type
            else
                return null;  // If not, cannot resolve
        }
    }
}